#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<limits.h>
#include<iterator>
#include<time.h>

using std::cin;
using std::cout;
using std::vector;
using std::pair;
using std::make_pair;

const int white = 0;
const int grey = 1;
const int black = 2;

typedef vector<vector<int> > Graph;

void addEdge(Graph &graph, int v, int u) {
    graph[v].push_back(u);
    return;
}

void dfs_cycle(Graph &graph, vector<int> &color, int v, bool &cycle) {
    color[v] = grey;
    for (int to : graph[v]) {
        if (color[to] == grey) {
            cycle = true;
            return;
        }
        if (color[to] == white) {
            dfs_cycle(graph, color, to, cycle);
        }
    }
    color[v] = black;
    return;
}

bool find_cycle(Graph &graph, int sz) {
    vector<int> color;
    color.assign(sz, white);
    bool is_cycle = false;
    for (int v = 0; v < sz; ++v) {
        if (color[v] == white) {
            dfs_cycle(graph, color, v, is_cycle);
        }
    }
    return is_cycle;
}

void dfs_simple(Graph &graph, vector<bool> &used, int v, vector<int> &sorted) {
	used[v] = true;
	for (int to : graph[v]) {
		if (!used[to])
			dfs_simple(graph, used, to, sorted);
	}
	sorted.push_back(v);
	return;
}

void topological_sort(Graph &graph, int sz, vector<int> &sorted) {
    vector<bool> used;
    used.assign(sz, false);
	for (int v = 0; v < sz; ++v) {
		if (!used[v] && graph[v].size() != 0) {
			dfs_simple(graph, used, v, sorted);
		}
    }
	std::reverse(sorted.begin(), sorted.end());
	return;
}

bool is_start(int n, int sz) {
    return n < sz / 2;
}

void build_segments(vector<int> &order, int sz, vector<pair<int, int> > &segments) {
    int x = 0;
    for (int v : order) {
        if (is_start(v, sz)) {
            segments[v].first = x;
        } else {
            segments[v - sz / 2].second = x;
        }
        ++x;
    }
    return;
}

int main() {
    int n, a, b;
    cin >> n >> a >> b;
    Graph order(2 * n);
    for (int i = 0; i < n; ++i) {
        addEdge(order, i, i + n);
    }
    int first_segment = 0, second_segment = 0;
    for (int i = 0; i < a; ++i) {
        cin >> first_segment >> second_segment;
        --first_segment, --second_segment;
        int first_segment_finish = first_segment + n;
        int second_segment_start = second_segment;
        addEdge(order, first_segment_finish, second_segment_start);
    }
    for (int i = 0; i < b; ++i) {
        cin >> first_segment >> second_segment;
        --first_segment, --second_segment;
        int first_segment_start = first_segment;
        int first_segment_finish = first_segment + n;
        int second_segment_start = second_segment;
        int second_segment_finish = second_segment + n;
        addEdge(order, first_segment_start, second_segment_finish);
        addEdge(order, second_segment_start, first_segment_finish);
    }
    if (find_cycle(order, 2 * n)) {
        cout << "Impossible\n";
        return 0;
    }
    vector<int> sorted;
    topological_sort(order, 2 * n, sorted);
    vector<pair<int, int> > segments;
    segments.assign(n, make_pair(-1, -1));
    build_segments(sorted, 2 * n, segments);
    for (int i = 0; i < n; ++i) {
        cout << segments[i].first << " " << segments[i].second << "\n";
    }
    return 0;
}
